#ifndef xEngineWrite_h_h_h_h
#define xEngineWrite_h_h_h_h


#include "stdafx.h"
#include "COLLADAFWIWriter.h"
#include "COLLADAFWUniqueId.h"
#include "COLLADAFWVisualScene.h"
#include "COLLADAFWLibraryNodes.h"
#include "COLLADAFWMaterial.h"
#include "COLLADAFWEffect.h"
#include "COLLADAFWImage.h"

#include "COLLADABUURI.h"
#include "Math/COLLADABUMathMatrix4.h"


namespace XE
{
	


	class xEngineWrite :public COLLADAFW::IWriter
	{
		friend class xMeshWrite;
		friend class xBaseWrite;
	public:

		enum Runs
		{
			SCENEGRAPH_RUN,
			GEOMETRY_RUN
		};
		typedef std::list<COLLADAFW::LibraryNodes> LibraryNodesList;

		struct InstanceGeometryInfo
		{
			InstanceGeometryInfo( COLLADAFW::InstanceGeometry* _fwInstanceGeometry, const COLLADABU::Math::Matrix4& _worldMatrix, \
				const xString&nodeName)
				:  fwInstanceGeometry(_fwInstanceGeometry), worldMatrix(_worldMatrix),m_Name(nodeName){}
			COLLADAFW::InstanceGeometry* fwInstanceGeometry;
			COLLADABU::Math::Matrix4 worldMatrix;
			xString m_Name;
		};

		typedef std::multimap<COLLADAFW::UniqueId, InstanceGeometryInfo> GeometryUniqueIdInstanceGeometryInfoMap;

		/** Maps unique ids of framework materials to the corresponding framework material.*/
		typedef std::map<COLLADAFW::UniqueId, COLLADAFW::Material> UniqueIdFWMaterialMap;

		/** Maps unique ids of framework images to the corresponding framework image.*/
		typedef std::map<COLLADAFW::UniqueId, COLLADAFW::Image> UniqueIdFWImageMap;

		/** Maps unique ids of framework effects to the corresponding framework material.*/
		typedef std::map<COLLADAFW::UniqueId, COLLADAFW::Effect> UniqueIdFWEffectMap;


		typedef std::map<COLLADAFW::UniqueId,xMesh*>   UniqueIdMeshMap;


		enum Severity
		{
			SEVERITY_INFORMATION,
			SEVERITY_WARNING,
			_SEVERITY_ERROR
		};


		Runs mCurrentRun;

		const COLLADAFW::VisualScene* mVisualScene;
		LibraryNodesList mLibrayNodesList;

		GeometryUniqueIdInstanceGeometryInfoMap mGeometryUniqueIdInstanceGeometryInfoMap;

		UniqueIdFWMaterialMap mUniqueIdFWMaterialMap;
		UniqueIdFWImageMap mUniqueIdFWImageMap;
		UniqueIdFWEffectMap mUniqueIdFWEffectMap;

		UniqueIdMeshMap mUniqueIdMeshMap;



		GeometryUniqueIdInstanceGeometryInfoMap& getGeometryUniqueIdInstanceGeometryInfoMap() { return mGeometryUniqueIdInstanceGeometryInfoMap; }

		UniqueIdFWMaterialMap& getUniqueIdFWMaterialMap() { return mUniqueIdFWMaterialMap; }

		UniqueIdFWImageMap& getUniqueIdFWImageMap() { return mUniqueIdFWImageMap; }

		UniqueIdFWEffectMap& getUniqueIdFWEffectMap() { return mUniqueIdFWEffectMap; }

		UniqueIdMeshMap&     GetUniqueIdFWMeshMap(){return mUniqueIdMeshMap;}





	public:
		xEngineWrite(const xString& fileName,xSceneManager* pSceneManager);
		~xEngineWrite(void);



		bool write();

		void cancel(const xString& errorMessage);

		/** This is the method called. The writer hast to prepare to receive data.*/
		void start();

		/** This method is called after the last write* method. No other methods will be called after this.*/
		void finish();

		/** When this method is called, the writer must write the global document asset.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeGlobalAsset ( const COLLADAFW::FileInfo* asset );

		/** When this method is called, the writer must write the scene.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeScene ( const COLLADAFW::Scene* scene ) ;

		/** When this method is called, the writer must write the entire visual scene.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeVisualScene ( const COLLADAFW::VisualScene* visualScene );

		/** When this method is called, the writer must handle all nodes contained in the 
		library nodes.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeLibraryNodes ( const COLLADAFW::LibraryNodes* libraryNodes );

		/** When this method is called, the writer must write the geometry.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeGeometry ( const COLLADAFW::Geometry* geometry ) ;

		/** When this method is called, the writer must write the material.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeMaterial( const COLLADAFW::Material* material );

		/** When this method is called, the writer must write the effect.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeEffect( const COLLADAFW::Effect* effect );

		/** When this method is called, the writer must write the camera.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeCamera( const COLLADAFW::Camera* camera );

		/** When this method is called, the writer must write the image.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeImage( const COLLADAFW::Image* image );

		/** When this method is called, the writer must write the light.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeLight( const COLLADAFW::Light* light );

		/** When this method is called, the writer must write the Animation.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeAnimation( const COLLADAFW::Animation* animation ) ;

		/** When this method is called, the writer must write the AnimationList.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeAnimationList( const COLLADAFW::AnimationList* animationList ) ;

		/** When this method is called, the writer must write the skin controller data.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeSkinControllerData( const COLLADAFW::SkinControllerData* skinControllerData ) ;

		/** When this method is called, the writer must write the controller.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeController( const COLLADAFW::Controller* controller ) ;

		/** When this method is called, the writer must write the formulas. All the formulas of the entire
		COLLADA file are contained in @a formulas.
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeFormulas( const COLLADAFW::Formulas* formulas ) ;

		/** When this method is called, the writer must write the kinematics scene. 
		@return The writer should return true, if writing succeeded, false otherwise.*/
		bool writeKinematicsScene( const COLLADAFW::KinematicsScene* kinematicsScene ) ;


	protected:

		bool BulidScene();

		xString m_FileName;

		xSceneManager* m_pSceneManager;

	};
}


#endif
